package com.tsysytems.gui;

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.toedter.calendar.JDateChooser;
import com.toedter.calendar.JSpinnerDateEditor;
import com.tsystems.entities.Passenger;
import com.tsystems.entities.Station;
import com.tsystems.entities.TimeTableElement;
import com.tsystems.entities.Train;
import com.tsystems.protocol.client.ClientPassenger;

public class BuyTicketPanel extends JPanel {

	Passenger currentPassenger;

	private JComboBox arrivalStationBox;
	private JComboBox departureStationBox;
	private JDateChooser arrivalTimeJSDE;
	private JDateChooser departureTimeJSDE;
	private HashMap<Train, List<TimeTableElement>> path;

	FindTrainTable trainTable = new FindTrainTable();
	BuyTicketTableElementTable pathTable = new BuyTicketTableElementTable();
	private static final long serialVersionUID = 6489712085149821505L;

	Logger logger = LoggerFactory.getLogger(getClass());

	public BuyTicketPanel() {
		super(new GridBagLayout());

		setBorder(new TitledBorder("Подбор поезда и покупка билета"));

		trainTable.setSelectListener(new ListSelectionListener() {

			public void valueChanged(ListSelectionEvent e) {
				if (trainTable.getSelectedTrain() != null) {
					pathTable.updateTable(path.get(trainTable
							.getSelectedTrain()));
				}

			}
		});
		pathTable.setSelectListener(new ListSelectionListener() {

			public void valueChanged(ListSelectionEvent arg0) {

			}
		});
		add(createFindTrainPanel(), new GridBagConstraints(0, 0, 1, 1, 1.0,
				0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
				new Insets(-5, 0, 0, 0), 0, 0));
		JPanel result = new JPanel(new GridBagLayout());
		result.add(new JScrollPane(trainTable), new GridBagConstraints(0, 0, 1,
				1, 1.0, 1.0, GridBagConstraints.CENTER,
				GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
		result.add(new JScrollPane(pathTable), new GridBagConstraints(1, 0, 3,
				1, 3.0, 1.0, GridBagConstraints.CENTER,
				GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 3, 0));

		add(result, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0,
				GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0,
						0, 0, 0), 0, 0));
		add(createButtonPanel(), new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0,
				GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
				new Insets(-5, 0, 0, 0), 0, 0));

	}

	public JPanel createFindTrainPanel() {

		JPanel result = new JPanel(new GridBagLayout());
		result.add(new JLabel("Станция отправления"), new GridBagConstraints(1,
				0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
				GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 10, 10));
		departureStationBox = new JComboBox(new Vector<Station>(ClientPassenger
				.getInstance().viewStations()));
		result.add(departureStationBox, new GridBagConstraints(1, 1, 1, 1, 1.0,
				0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
				new Insets(0, 1, 1, 0), 0, 0));

		result.add(new JLabel("Время отправления"), new GridBagConstraints(2,
				0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
				GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 10, 10));
		departureTimeJSDE = new JDateChooser(Calendar.getInstance().getTime());
		;
		result.add(departureTimeJSDE, new GridBagConstraints(2, 1, 1, 1, 1.0,
				0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
				new Insets(0, 1, 1, 0), 0, 0));

		result.add(new JLabel("Станция прибытия"), new GridBagConstraints(3, 0,
				1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
				GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 10, 10));
		arrivalStationBox = new JComboBox(new Vector<Station>(ClientPassenger
				.getInstance().viewStations()));
		result.add(arrivalStationBox, new GridBagConstraints(3, 1, 1, 1, 1.0,
				0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
				new Insets(0, 1, 1, 0), 0, 0));

		result.add(new JLabel("Время прибытия"), new GridBagConstraints(4, 0,
				1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
				GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 10, 10));
		arrivalTimeJSDE = new JDateChooser(Calendar.getInstance().getTime());
		;
		result.add(arrivalTimeJSDE, new GridBagConstraints(4, 1, 1, 1, 1.0,
				0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
				new Insets(0, 1, 1, 0), 0, 0));

		JButton okBtn = new JButton("Подобрать");
		okBtn.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				Date departureTime = departureTimeJSDE.getDate();
				if (departureTime != null) {
					Calendar currentTime = Calendar.getInstance();
					currentTime.setTime(departureTime);

					if (currentTime.get(Calendar.DAY_OF_MONTH) == Calendar
							.getInstance().get(Calendar.DAY_OF_MONTH)
							&& currentTime.get(Calendar.MONTH) == Calendar
									.getInstance().get(Calendar.MONTH)
							&& currentTime.get(Calendar.YEAR) == Calendar
									.getInstance().get(Calendar.YEAR)) {
						currentTime.add(Calendar.MINUTE, 10);

					} else {
						currentTime.set(Calendar.HOUR,
								currentTime.getMinimum(Calendar.HOUR));
						currentTime.set(Calendar.MINUTE,
								currentTime.getMinimum(Calendar.MINUTE));
						currentTime.set(Calendar.SECOND,
								currentTime.getMinimum(Calendar.SECOND));
					}
					departureTime = currentTime.getTime();
				} else {
					JOptionPane.showMessageDialog(BuyTicketPanel.this,
							"Дата отправления должна быть задана!");
					return;
				}

				Date arrivalTime = arrivalTimeJSDE.getDate();
				if (arrivalTime != null) {
					Calendar currentTime = Calendar.getInstance();
					currentTime.setTime(arrivalTime);
					currentTime.set(Calendar.HOUR, 23);
					currentTime.set(Calendar.MINUTE, 59);
					currentTime.set(Calendar.SECOND, 59);
					arrivalTime = currentTime.getTime();

				} else {
					JOptionPane.showMessageDialog(BuyTicketPanel.this,
							"Дата прибытия должна быть задана!");
					return;
				}
				TimeTableElement passenger = new TimeTableElement(new Train(
						"Test", 150), (Station) departureStationBox
						.getItemAt(departureStationBox.getSelectedIndex()),
						(Station) arrivalStationBox.getItemAt(arrivalStationBox
								.getSelectedIndex()), departureTime,
						arrivalTime);

				if (validate(passenger)) {
					path = ClientPassenger.getInstance().findTrain(
							passenger.getDepartureStation(),
							passenger.getArrivalStation(),
							passenger.getDepartureTime(),
							passenger.getArrivalTime());
					trainTable.updateTable(new ArrayList<Train>(path.keySet()));
					if (trainTable.getSelectedTrain() != null) {
						pathTable.updateTable(path.get(trainTable
								.getSelectedTrain()));
					} else {
						pathTable.removeAll();
						pathTable.updateUI();
					}
				}

			}
		});

		result.add(okBtn, new GridBagConstraints(5, 1, 1, 1, 1.0, 0.0,
				GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(
						0, 1, 1, 0), 0, 0));

		return result;
	}

	private boolean validate(TimeTableElement passenger) {

		ValidatorFactory vf = Validation.buildDefaultValidatorFactory();
		Validator validator = vf.getValidator();

		String message = validate(passenger, validator);
		if (message != null) {
			JOptionPane.showMessageDialog(BuyTicketPanel.this, message);
			return false;
		}

		return true;
	}

	public String validate(Object object, Validator validator) {
		Set<ConstraintViolation<Object>> constraintViolations = validator
				.validate(object);
		String resultString = null;

		if (constraintViolations.size() > 0) {
			resultString = "";

			for (ConstraintViolation<Object> cv : constraintViolations) {
				resultString += cv.getMessage() + "\n";
			}
		}
		return resultString;
	}

	public JPanel createButtonPanel() {

		JPanel result = new JPanel(new FlowLayout());
		JButton buyTicket = new JButton("Купить билет");
		buyTicket.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				if (trainTable.getSelectedTrain() != null) {
					List<TimeTableElement> elements = path.get(trainTable
							.getSelectedTrain());
					String result = ClientPassenger.getInstance().buyTicket(
							elements.get(0).getDepartureStation(),
							elements.get(elements.size() - 1)
									.getArrivalStation(),
							elements.get(0).getDepartureTime(),
							elements.get(0).getTrain(),
							elements.get(elements.size() - 1).getArrivalTime());

					if (result == null) {
						JOptionPane
								.showMessageDialog(BuyTicketPanel.this,
										"Произошла внутренняя ошибка программы, обратитесь к администратору!");
					} else {
						JOptionPane.showMessageDialog(BuyTicketPanel.this,
								result);

					}

				}

			}
		});
		result.add(buyTicket);
		return result;
	}
}
